#!/usr/bin/env node

/**
 * 清理残留的 Node.js 进程
 *
 * 使用方法：
 *   node app/scripts/cleanup-node-processes.mjs
 *   node app/scripts/cleanup-node-processes.mjs --force
 */

import { exec } from 'node:child_process'
import { promisify } from 'node:util'

const execAsync = promisify(exec)

async function cleanupNodeProcesses() {
  const isWindows = process.platform === 'win32'
  const forceFlag = process.argv.includes('--force')
  const killAll = process.argv.includes('--all') // 包括 Cursor 的进程

  console.log('='.repeat(80))
  console.log('清理残留的 Node.js 进程')
  console.log('='.repeat(80))

  if (!killAll) {
    console.log('\n⚠️  注意: 默认只清理测试脚本的进程')
    console.log('   如果 Cursor 或其他应用的 Node.js 进程也被终止，使用 --all 参数')
  }

  try {
    if (isWindows) {
      // Windows 使用 tasklist 和 taskkill
      console.log('\n📋 查找 Node.js 进程...')

      // 查找所有 node.exe 进程
      const { stdout } = await execAsync('tasklist /FI "IMAGENAME eq node.exe" /FO CSV /NH')
      let lines = stdout.trim().split('\n').filter(line => line.trim())

      // 如果不是 --all 模式，尝试过滤掉 Cursor 的进程
      if (!killAll) {
        try {
          // 获取 Cursor 的 PID
          const { stdout: cursorStdout } = await execAsync('tasklist /FI "IMAGENAME eq Cursor.exe" /FO CSV /NH')
          const cursorLines = cursorStdout.trim().split('\n').filter(line => line.trim())
          const cursorPids = new Set()

          for (const line of cursorLines) {
            const parts = line.split(',').map(s => s.replace(/"/g, '').trim())
            if (parts.length >= 2) {
              cursorPids.add(parts[1])
            }
          }

          // 获取进程树，找出 Cursor 的子进程
          const cursorChildPids = new Set()
          for (const cursorPid of cursorPids) {
            try {
              const { stdout: treeStdout } = await execAsync(`wmic process where "ParentProcessId=${cursorPid}" get ProcessId /format:value`)
              const treeLines = treeStdout.split('\n').filter(l => l.includes('ProcessId='))
              for (const treeLine of treeLines) {
                const pid = treeLine.split('=')[1]?.trim()
                if (pid) {
                  cursorChildPids.add(pid)
                  // 递归查找子进程的子进程
                  try {
                    const { stdout: subTreeStdout } = await execAsync(`wmic process where "ParentProcessId=${pid}" get ProcessId /format:value`)
                    const subTreeLines = subTreeStdout.split('\n').filter(l => l.includes('ProcessId='))
                    for (const subTreeLine of subTreeLines) {
                      const subPid = subTreeLine.split('=')[1]?.trim()
                      if (subPid)
                        cursorChildPids.add(subPid)
                    }
                  }
                  catch {
                    // 忽略错误
                  }
                }
              }
            }
            catch {
              // 忽略错误
            }
          }

          // 过滤掉 Cursor 的子进程
          const originalCount = lines.length
          lines = lines.filter((line) => {
            const parts = line.split(',').map(s => s.replace(/"/g, '').trim())
            if (parts.length >= 2) {
              const pid = parts[1]
              return !cursorChildPids.has(pid) && !cursorPids.has(pid)
            }
            return true
          })

          if (lines.length < originalCount) {
            console.log(`📋 已过滤 ${originalCount - lines.length} 个 Cursor 相关的进程`)
          }
        }
        catch {
          // 如果无法过滤，使用所有进程
          console.log('⚠️  无法过滤 Cursor 进程，将处理所有 Node.js 进程')
        }
      }

      if (lines.length === 0) {
        console.log('✅ 没有找到 Node.js 进程')
        return
      }

      console.log(`\n找到 ${lines.length} 个 Node.js 进程:`)

      // 解析进程信息
      const processes = []
      for (const line of lines) {
        const parts = line.split(',').map(s => s.replace(/"/g, '').trim())
        if (parts.length >= 2) {
          processes.push({
            pid: parts[1],
            name: parts[0],
            memory: parts.length > 4 ? parts[4] : 'N/A',
          })
        }
      }

      // 显示进程信息
      processes.forEach((proc, idx) => {
        console.log(`  ${idx + 1}. PID: ${proc.pid.padStart(8)} | 内存: ${proc.memory}`)
      })

      if (!forceFlag) {
        console.log('\n⚠️  警告: 这将终止所有 Node.js 进程')
        console.log('按 Ctrl+C 取消，或等待5秒后继续...')
        await new Promise(resolve => setTimeout(resolve, 5000))
      }

      console.log('\n🔄 正在终止进程...')

      // 多次尝试终止进程（有些进程可能需要多次尝试）
      let remaining = processes.length
      for (let attempt = 1; attempt <= 3; attempt++) {
        try {
          const { stdout, stderr } = await execAsync('taskkill /F /IM node.exe /T')

          // taskkill 的输出可能在 stdout 或 stderr
          const output = (stdout || stderr || '').trim()
          if (output && !output.includes('ERROR')) {
            // 只显示成功消息，不显示每一行的详细信息
            if (output.includes('SUCCESS')) {
              const successCount = (output.match(/SUCCESS/g) || []).length
              console.log(`✓ 已终止 ${successCount} 个进程`)
            }
          }

          // 等待一下让进程完全终止
          await new Promise(resolve => setTimeout(resolve, 1000))

          // 检查剩余进程
          const { stdout: checkStdout } = await execAsync('tasklist /FI "IMAGENAME eq node.exe" /FO CSV /NH')
          const remainingLines = checkStdout.trim().split('\n').filter(line => line.trim())
          remaining = remainingLines.length

          if (remaining === 0) {
            console.log('✅ 所有 Node.js 进程已成功终止')
            break
          }

          if (attempt < 3) {
            console.log(`⚠️  仍有 ${remaining} 个进程，尝试第 ${attempt + 1} 次...`)
          }
        }
        catch (error) {
          const errorStderr = error?.stderr || ''
          const errorStdout = error?.stdout || ''

          // taskkill 的输出可能在 stderr 中（Windows 的特性）
          const output = (errorStdout || errorStderr || '').trim()

          // 检查是否成功（taskkill 成功时输出包含 SUCCESS）
          if (output.includes('SUCCESS')) {
            const successCount = (output.match(/SUCCESS/g) || []).length
            console.log(`✓ 已终止 ${successCount} 个进程`)

            // 再次检查
            await new Promise(resolve => setTimeout(resolve, 1000))
            try {
              const { stdout: checkStdout } = await execAsync('tasklist /FI "IMAGENAME eq node.exe" /FO CSV /NH')
              const remainingLines = checkStdout.trim().split('\n').filter(line => line.trim())
              remaining = remainingLines.length

              if (remaining === 0) {
                console.log('✅ 所有 Node.js 进程已成功终止')
                break
              }
              else if (attempt < 3) {
                console.log(`⚠️  仍有 ${remaining} 个进程，尝试第 ${attempt + 1} 次...`)
              }
            }
            catch {
              // 忽略检查错误
            }
          }
          else if (output.includes('not found') || output.includes('找不到')) {
            console.log('✅ 没有需要终止的进程')
            remaining = 0
            break
          }
        }
      }

      if (remaining > 0) {
        console.log(`\n⚠️  仍有 ${remaining} 个进程未清理`)
        console.log('这些进程可能需要管理员权限才能终止')
        console.log('建议：以管理员身份运行此脚本，或手动在任务管理器中终止')
      }
    }
    else {
      // Linux/Mac 使用 ps 和 kill
      console.log('\n📋 查找 Node.js 进程...')

      const { stdout } = await execAsync('ps aux | grep node | grep -v grep')
      const lines = stdout.trim().split('\n').filter(line => line.trim())

      if (lines.length === 0) {
        console.log('✅ 没有找到 Node.js 进程')
        return
      }

      console.log(`\n找到 ${lines.length} 个 Node.js 进程:`)
      lines.forEach((line, idx) => {
        const parts = line.split(/\s+/)
        console.log(`  ${idx + 1}. PID: ${parts[1]} | ${parts.slice(10).join(' ')}`)
      })

      if (!forceFlag) {
        console.log('\n⚠️  警告: 这将终止所有 Node.js 进程')
        console.log('按 Ctrl+C 取消，或等待5秒后继续...')
        await new Promise(resolve => setTimeout(resolve, 5000))
      }

      console.log('\n🔄 正在终止进程...')

      // 提取所有 PID
      const pids = lines.map(line => line.split(/\s+/)[1])

      for (const pid of pids) {
        try {
          await execAsync(`kill -9 ${pid}`)
        }
        catch {
          // 忽略错误，进程可能已经结束
        }
      }

      console.log('✅ 已终止所有 Node.js 进程')
    }
  }
  catch (error) {
    console.error('\n❌ 清理失败:', error)
    process.exit(1)
  }
}

cleanupNodeProcesses().catch(console.error)
